﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq.Expressions;
using Moq;
using Myotragus.Data;
using Myotragus.Data.Containers;
using Myotragus.Data.Domain;
using Myotragus.Data.Emit;
using NHibernate;
using NHibernate.Engine;
using NHibernate.Stat;
using NHibernate.Type;

namespace Myotragus.Store.Model.Tests.Mocks
{
  public class MockSession : ISession
  {
    #region Implementation of IDisposable

    public void Dispose()
    {
      throw new NotImplementedException();
    }

    #endregion

    #region Implementation of ISession

    public void Flush()
    {
      throw new NotImplementedException();
    }

    public IDbConnection Disconnect()
    {
      throw new NotImplementedException();
    }

    public void Reconnect()
    {
      throw new NotImplementedException();
    }

    public void Reconnect(IDbConnection connection)
    {
      throw new NotImplementedException();
    }

    public IDbConnection Close()
    {
      throw new NotImplementedException();
    }

    public void CancelQuery()
    {
      throw new NotImplementedException();
    }

    public bool IsDirty()
    {
      throw new NotImplementedException();
    }

    public object GetIdentifier(object obj)
    {
      throw new NotImplementedException();
    }

    public bool Contains(object obj)
    {
      throw new NotImplementedException();
    }

    public void Evict(object obj)
    {
      throw new NotImplementedException();
    }

    public object Load(Type theType, object id, LockMode lockMode)
    {
      throw new NotImplementedException();
    }

    public object Load(string entityName, object id, LockMode lockMode)
    {
      throw new NotImplementedException();
    }

    public object Load(Type theType, object id)
    {
      throw new NotImplementedException();
    }

    public T Load<T>(object id, LockMode lockMode)
    {
      throw new NotImplementedException();
    }

    public T Load<T>(object id)
    {
      throw new NotImplementedException();
    }

    public object Load(string entityName, object id)
    {
      throw new NotImplementedException();
    }

    public void Load(object obj, object id)
    {
      throw new NotImplementedException();
    }

    public void Replicate(object obj, ReplicationMode replicationMode)
    {
      throw new NotImplementedException();
    }

    public void Replicate(string entityName, object obj, ReplicationMode replicationMode)
    {
      throw new NotImplementedException();
    }

    public object Save(object obj)
    {
      throw new NotImplementedException();
    }

    public void Save(object obj, object id)
    {
      throw new NotImplementedException();
    }

    public object Save(string entityName, object obj)
    {
      throw new NotImplementedException();
    }

    public void SaveOrUpdate(object obj)
    {
      throw new NotImplementedException();
    }

    public void SaveOrUpdate(string entityName, object obj)
    {
      throw new NotImplementedException();
    }

    public void Update(object obj)
    {
      throw new NotImplementedException();
    }

    public void Update(object obj, object id)
    {
      throw new NotImplementedException();
    }

    public void Update(string entityName, object obj)
    {
      throw new NotImplementedException();
    }

    public object Merge(object obj)
    {
      throw new NotImplementedException();
    }

    public object Merge(string entityName, object obj)
    {
      throw new NotImplementedException();
    }

    public void Persist(object obj)
    {
      throw new NotImplementedException();
    }

    public void Persist(string entityName, object obj)
    {
      throw new NotImplementedException();
    }

    public object SaveOrUpdateCopy(object obj)
    {
      throw new NotImplementedException();
    }

    public object SaveOrUpdateCopy(object obj, object id)
    {
      throw new NotImplementedException();
    }

    public void Delete(object obj)
    {
      throw new NotImplementedException();
    }

    public void Delete(string entityName, object obj)
    {
      throw new NotImplementedException();
    }

    public int Delete(string query)
    {
      throw new NotImplementedException();
    }

    public int Delete(string query, object value, IType type)
    {
      throw new NotImplementedException();
    }

    public int Delete(string query, object[] values, IType[] types)
    {
      throw new NotImplementedException();
    }

    public void Lock(object obj, LockMode lockMode)
    {
      throw new NotImplementedException();
    }

    public void Lock(string entityName, object obj, LockMode lockMode)
    {
      throw new NotImplementedException();
    }

    public void Refresh(object obj)
    {
      throw new NotImplementedException();
    }

    public void Refresh(object obj, LockMode lockMode)
    {
      throw new NotImplementedException();
    }

    public LockMode GetCurrentLockMode(object obj)
    {
      throw new NotImplementedException();
    }

    public ITransaction BeginTransaction()
    {
      throw new NotImplementedException();
    }

    public ITransaction BeginTransaction(IsolationLevel isolationLevel)
    {
      throw new NotImplementedException();
    }

    public ICriteria CreateCriteria<T>() where T : class
    {
      throw new NotImplementedException();
    }

    public ICriteria CreateCriteria<T>(string alias) where T : class
    {
      throw new NotImplementedException();
    }

    public ICriteria CreateCriteria(Type persistentClass)
    {
      throw new NotImplementedException();
    }

    public ICriteria CreateCriteria(Type persistentClass, string alias)
    {
      throw new NotImplementedException();
    }

    public ICriteria CreateCriteria(string entityName)
    {
      throw new NotImplementedException();
    }

    public ICriteria CreateCriteria(string entityName, string alias)
    {
      throw new NotImplementedException();
    }

    public IQueryOver<T, T> QueryOver<T>() where T : class
    {
      throw new NotImplementedException();
    }

    public IQueryOver<T, T> QueryOver<T>(Expression<Func<T>> alias) where T : class
    {
      throw new NotImplementedException();
    }

    public IQuery CreateQuery(string queryString)
    {
      throw new NotImplementedException();
    }

    public IQuery CreateQuery(IQueryExpression queryExpression)
    {
      throw new NotImplementedException();
    }

    public IQuery CreateFilter(object collection, string queryString)
    {
      throw new NotImplementedException();
    }

    public IQuery GetNamedQuery(string queryName)
    {
      throw new NotImplementedException();
    }

    public ISQLQuery CreateSQLQuery(string queryString)
    {
      throw new NotImplementedException();
    }

    public void Clear()
    {
      throw new NotImplementedException();
    }

    public object Get(Type clazz, object id)
    {
      throw new NotImplementedException();
    }

    public object Get(Type clazz, object id, LockMode lockMode)
    {
      throw new NotImplementedException();
    }

    public object Get(string entityName, object id)
    {
      throw new NotImplementedException();
    }

    public T Get<T>(object id)
    {
      throw new NotImplementedException();
    }

    public T Get<T>(object id, LockMode lockMode)
    {
      throw new NotImplementedException();
    }

    public string GetEntityName(object obj)
    {
      throw new NotImplementedException();
    }

    public IFilter EnableFilter(string filterName)
    {
      throw new NotImplementedException();
    }

    public IFilter GetEnabledFilter(string filterName)
    {
      throw new NotImplementedException();
    }

    public void DisableFilter(string filterName)
    {
      throw new NotImplementedException();
    }

    public IMultiQuery CreateMultiQuery()
    {
      throw new NotImplementedException();
    }

    public ISession SetBatchSize(int batchSize)
    {
      throw new NotImplementedException();
    }

    public ISessionImplementor GetSessionImplementation()
    {
      throw new NotImplementedException();
    }

    public IMultiCriteria CreateMultiCriteria()
    {
      throw new NotImplementedException();
    }

    public ISession GetSession(EntityMode entityMode)
    {
      throw new NotImplementedException();
    }

    public EntityMode ActiveEntityMode { get; private set; }
    public FlushMode FlushMode { get; set; }
    public CacheMode CacheMode { get; set; }
    public ISessionFactory SessionFactory { get; private set; }
    public IDbConnection Connection { get; private set; }
    public bool IsOpen { get; private set; }
    public bool IsConnected { get; private set; }
    public ITransaction Transaction { get; private set; }
    public ISessionStatistics Statistics { get; private set; }

    #endregion
  }

  public class ReadWriteRepo<TEntity> : Repository<TEntity>,
    IReadRepository<TEntity>, IWriteRepository<TEntity>
    where TEntity : IEntity
  {
    public ReadWriteRepo(IEntitiesContainer entities) : base(entities)
    {
    }
  }

  public class MockServices
  {
    public static IDictionary<Type, IList<Type>> DicData = new Dictionary<Type, IList<Type>>();

    public static ISessionFactoryAdapter SessionFactoryHolder()
    {
      var mock = new Mock<ISessionFactoryAdapter>();

      mock.Setup(m => m.OpenSession()).Returns(Session);

      return mock.Object;
    }

    public static IEntitiesContainer Entities<TEntity>() where TEntity : IEntity
    {
      var mock = new Mock<IEntitiesContainer>();
      var dyn = new DynamicAssembly();
      var auto = new AutoProperties(dyn);
      var type = typeof(TEntity);

      var impl = auto.GetImplementation(type);
      
      mock.Setup(t => t.Create(type)).Returns((IEntity)Activator.CreateInstance(impl));
      mock.Setup(t => t.Create<TEntity>()).Returns((TEntity)Activator.CreateInstance(impl));

      return mock.Object;
    }

    public static IServicesContainer Services()
    {
      var mock = new Mock<IServicesContainer>();

      mock.Setup(m => m.Resolve<ISessionFactoryAdapter>()).Returns(SessionFactoryHolder());

      return mock.Object;
    }

    public static ISession Session()
    {
      var mock = new Mock<ISession>();

      mock.SetupAllProperties();
      mock.Setup(s => s.BeginTransaction()).Returns(Transaction());
      
      return mock.Object;
    }

    public static ITransaction Transaction()
    {
      var mock = new Mock<ITransaction>();

      return mock.Object;
    }

    public static ICriteria Criteria()
    {
      var mock = new Mock<ICriteria>();

      return mock.Object;
    }
  }
}
